scene.asset["luxorEngine"] = LuaEngine()

--#### Head turning ####--
scene.asset["luxorEngine"]:registerKey( "a", "turnHead( 1 )" )		-- Associate "a" to turn head left
scene.asset["luxorEngine"]:registerKey( "d", "turnHead( -1 )" )		-- Associate "d" to turn head right

luxor_active = 0
luxor_headRotation = 0

function turnHead( dir, rot, frame )
	frame = frame or luxor_active
	rot = rot or 5
	if( luxor_headRotation + (rot * dir) <= domeRotationLimit and luxor_headRotation + (rot * dir) >= -domeRotationLimit )then
		scene.element["luxor"].frame[frame].base.beam1.beam2.beam3.dome.root:rotate( 0, rot * dir, 0 )
		luxor_headRotation = luxor_headRotation + ( rot * dir )
	end
end

--#### Movement ####--
scene.asset["luxorEngine"]:registerKey( "w", "jumpForward()" )
scene.asset["luxorEngine"]:registerKey( "s", "jumpBackwards()" )
scene.asset["luxorEngine"]:registerKey( "r", "rest()" )

luxor_resting = false

function jumpForward()
	if( luxor_resting )then
		rest()
	end
	
	local degRot = luxor_headRotation	
	scene.element["luxor"].frame[0].root:rotate( 0, degRot, 0 )					-- Rotate Frame 0 base to head direction
	scene.element["luxor"].frame[0].root:translate( 0, 0, 90 )					-- Persist movement of Frame 0
	
	-- Transition Frame 1 to 2
	scene.element["luxor"].frame[1].animationKeys.root.rotation.y = -degRot		-- Prepare animation keys (for interpolation)
	scene.element["luxor"].frame[1].animationKeys.dome.rotation.y = degRot		-- 
	scene.element["luxor"].frame[2].root:rotate( 0, degRot, 0 )					-- Rotate Frame 2 base to head direction
	animate( 1, 2, animationFrameSteps )										-- Do the animation
	scene.element["luxor"].frame[1].root:rotate( 0, degRot, 0 )					-- Rotate Frame 1 base to head direction
	scene.element["luxor"].frame[1].root:translate( 0, 0, 90 )					-- Persist movement of Frame 1
	scene.element["luxor"].frame[1].animationKeys.root.rotation.y = 0			-- Reset animation keys
	scene.element["luxor"].frame[1].animationKeys.dome.rotation.y = 0			-- 
	
	-- Transition Frame 2 to 3
	scene.element["luxor"].frame[3].root:rotate( 0, degRot, 0 )					-- Rotate Frame 3 base to head direction
	animate( 2, 3, animationFrameSteps )										-- Do the animation
	scene.element["luxor"].frame[2].root:translate( 0, 0, 90 )					-- Persist movement of Frame 2
	
	-- Transition Frame 3 to 4
	scene.element["luxor"].frame[4].root:rotate( 0, degRot, 0 )					-- Rotate Frame 4 base to head direction
	animate( 3, 4, animationFrameSteps )										-- Do the animation
	scene.element["luxor"].frame[3].root:translate( 0, 0, 90 )					-- Persist movement of Frame 3
	
	-- Transition Frame 4 to 1
	scene.element["luxor"].frame[1].animationKeys.root.translation.z = 90		-- Perpare animation keys (for interpolation)
	animate( 4, 1, animationFrameSteps )										-- Do the animation
	scene.element["luxor"].frame[4].root:translate( 0, 0, 90 )					-- Persist movement of Frame 4
	scene.element["luxor"].frame[1].animationKeys.root.translation.z = 0		-- Reset animation keys
end

function jumpBackwards()
	if( luxor_resting )then
		rest()
	end
	
	scene.element["luxor"].frame[3].animationKeys.root.translation.z = -50
	scene.element["luxor"].frame[4].animationKeys.root.translation.z = -90
	
	local degRot = luxor_headRotation	
	scene.element["luxor"].frame[0].root:rotate( 0, degRot, 0 )
	scene.element["luxor"].frame[0].root:translate( 0, 0, -90 )
	
	-- Transition Frame 1 to 2
	scene.element["luxor"].frame[1].animationKeys.root.rotation.y = -degRot
	scene.element["luxor"].frame[1].animationKeys.dome.rotation.y = degRot
	scene.element["luxor"].frame[2].root:rotate( 0, degRot, 0 )
	animate( 1, 2, animationFrameSteps )
	scene.element["luxor"].frame[1].root:rotate( 0, degRot, 0 )
	scene.element["luxor"].frame[1].root:translate( 0, 0, -90 )
	scene.element["luxor"].frame[1].animationKeys.root.rotation.y = 0
	scene.element["luxor"].frame[1].animationKeys.dome.rotation.y = 0
	
	-- Transition Frame 2 to 3
	scene.element["luxor"].frame[3].root:rotate( 0, degRot, 0 )
	animate( 2, 3, animationFrameSteps )
	scene.element["luxor"].frame[2].root:translate( 0, 0, -90 )
	
	-- Transition Frame 3 to 4
	scene.element["luxor"].frame[3].root:translate( 0, 0, -100 )
	scene.element["luxor"].frame[4].root:rotate( 0, degRot, 0 )
	animate( 3, 4, animationFrameSteps )
	scene.element["luxor"].frame[3].root:translate( 0, 0, 100 )
	scene.element["luxor"].frame[3].root:translate( 0, 0, -90 )
	
	-- Transition Frame 4 to 1
	scene.element["luxor"].frame[4].root:translate( 0, 0, -180 )
	scene.element["luxor"].frame[1].animationKeys.root.translation.z = -90
	animate( 4, 1, animationFrameSteps )
	scene.element["luxor"].frame[4].root:translate( 0, 0, 180 )
	scene.element["luxor"].frame[4].root:translate( 0, 0, -90 )
	scene.element["luxor"].frame[1].animationKeys.root.translation.z = 0
	
	scene.element["luxor"].frame[3].animationKeys.root.translation.z = 50
	scene.element["luxor"].frame[4].animationKeys.root.translation.z = 90
end

function rest()
	local degRot = luxor_headRotation
	if( luxor_resting )then
		animate( 0, 1, animationFrameSteps )
		turnHead( 1, degRot, 1 )
	else
		animate( 1, 0, animationFrameSteps )
		turnHead( 1, degRot, 0 )
	end
	luxor_resting = not luxor_resting
end


function animate( initFrame, finalFrame, steps )
	local animSteps = 0
	local ak1 = scene.element["luxor"].frame[initFrame].animationKeys
	local ak2 = scene.element["luxor"].frame[finalFrame].animationKeys
	local root = scene.element["luxor"].frame[initFrame].root
	local base = scene.element["luxor"].frame[initFrame].base.root
	local beam1 = scene.element["luxor"].frame[initFrame].base.beam1.root
	local beam2 = scene.element["luxor"].frame[initFrame].base.beam1.beam2.root
	local beam3 = scene.element["luxor"].frame[initFrame].base.beam1.beam2.beam3.root
	local dome  = scene.element["luxor"].frame[initFrame].base.beam1.beam2.beam3.dome.root
	while( animSteps < steps )do
		animSteps = animSteps + 1
		-- Interpolate to next frame
		root:translate( interpolateLinear( ak1.root.translation, ak2.root.translation, animSteps / steps ) )
		root:rotate   ( interpolateLinear( ak1.root.rotation,    ak2.root.rotation,    animSteps / steps ) )
		base:rotate   ( interpolateLinear( ak1.base.rotation,    ak2.base.rotation,    animSteps / steps ) )
		beam1:rotate  ( interpolateLinear( ak1.beam1.rotation,   ak2.beam1.rotation,   animSteps / steps ) )
		beam2:rotate  ( interpolateLinear( ak1.beam2.rotation,   ak2.beam2.rotation,   animSteps / steps ) )
		beam3:rotate  ( interpolateLinear( ak1.beam3.rotation,   ak2.beam3.rotation,   animSteps / steps ) )
		dome:rotate   ( interpolateLinear( ak1.dome.rotation,    ak2.dome.rotation,    animSteps / steps ) )
		-- Show changes
		updateView()
		wait( animationFrameTime / steps )
		-- Undo changes
		root:rotate   ( interpolateLinear( ak2.root.rotation,    ak1.root.rotation,    animSteps / steps ) )
		root:translate( interpolateLinear( ak2.root.translation, ak1.root.translation, animSteps / steps ) )
		base:rotate   ( interpolateLinear( ak2.base.rotation,    ak1.base.rotation,    animSteps / steps ) )
		beam1:rotate  ( interpolateLinear( ak2.beam1.rotation,   ak1.beam1.rotation,   animSteps / steps ) )
		beam2:rotate  ( interpolateLinear( ak2.beam2.rotation,   ak1.beam2.rotation,   animSteps / steps ) )
		beam3:rotate  ( interpolateLinear( ak2.beam3.rotation,   ak1.beam3.rotation,   animSteps / steps ) )
		dome:rotate   ( interpolateLinear( ak2.dome.rotation,    ak1.dome.rotation,    animSteps / steps ) )		
	end
	changeFrame( finalFrame )
end

function interpolateLinear( v1, v2, percent )
	return ( v2.x - v1.x ) * percent, ( v2.y - v1.y ) * percent, ( v2.z - v1.z ) * percent
end

function changeFrame( frame )
	scene.element["luxor"].root:setActive( scene.element["luxor"].frame[frame].root )
	scene.element["luxor"].frame[frame].base.beam1.beam2.beam3.dome.root:addChild( scene.light[1] )
	scene.element["luxor"].frame[frame].base.beam1.beam2.beam3.dome.bulb.root:addChild( scene.camera[1] )
	turnHead( 1, -luxor_headRotation )
	luxor_active = frame
	return 1
end

--#### Toon Shading ####--
scene.asset["luxorEngine"]:registerKey( "t", "toggleToonShading()" )
scene.asset["luxorEngine"]:registerKey( "+", "incToonWidth(0.2)" )
scene.asset["luxorEngine"]:registerKey( "-", "incToonWidth(-0.2)" )

function toggleToonShading()
	toonShading = not toonShading
	for k, v in pairs( scene.element["luxor"].frame )do
		local base  = v.base
		local beam1 = v.base.beam1
		local beam2 = v.base.beam1.beam2
		local beam3 = v.base.beam1.beam2.beam3
		local dome  = v.base.beam1.beam2.beam3.dome
		local bulb  = v.base.beam1.beam2.beam3.dome.bulb
		base.entity_a:setToonShading( toonShading )
		base.entity_b:setToonShading( toonShading )
		beam1.entity:setToonShading( toonShading )
		beam2.entity:setToonShading( toonShading )
		beam3.entity_a:setToonShading( toonShading )
		beam3.entity_b:setToonShading( toonShading )
		dome.entity_a:setToonShading( toonShading )
		dome.entity_b:setToonShading( toonShading )
		bulb.entity:setToonShading( toonShading )
	end
end

function incToonWidth( w )
	if( toonBorderWidth + w > 0 )then
		toonBorderWidth = toonBorderWidth + w
	end
	for k, v in pairs( scene.element["luxor"].frame )do
		local base  = v.base
		local beam1 = v.base.beam1
		local beam2 = v.base.beam1.beam2
		local beam3 = v.base.beam1.beam2.beam3
		local dome  = v.base.beam1.beam2.beam3.dome
		local bulb  = v.base.beam1.beam2.beam3.dome.bulb
		base.entity_a:setToonBorderWidth( toonBorderWidth )
		base.entity_b:setToonBorderWidth( toonBorderWidth )
		beam1.entity:setToonBorderWidth( toonBorderWidth )
		beam2.entity:setToonBorderWidth( toonBorderWidth )
		beam3.entity_a:setToonBorderWidth( toonBorderWidth )
		beam3.entity_b:setToonBorderWidth( toonBorderWidth )
		dome.entity_a:setToonBorderWidth( toonBorderWidth )
		dome.entity_b:setToonBorderWidth( toonBorderWidth )
		bulb.entity:setToonBorderWidth( toonBorderWidth )
	end
end

--#### Light ####--
scene.asset["luxorEngine"]:registerKey( "f", "toggleLight()" )

light_on = true

function toggleLight()
	light_on = not light_on
	scene.light[1]:enable( light_on )
end

--#### Camera ####--
scene.asset["luxorEngine"]:registerKey( "v", "toggleCamera()" )

active_camera = 0

function toggleCamera()
	if( active_camera == 0 )then
		active_camera = 1
	else
		active_camera = 0
	end
	scene.camera[active_camera]:setActive()
end
